#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <stdint.h>
#include "../common_defs.h"
#include "parser_for_quadruples.h"

// 全局变量定义
Quadruple *quadruples = NULL;   // 四元式数组
int quad_count = 0;             // 四元式计数
int temp_var_count = 0;         // 临时变量计数
int label_count = 0;            // 标签计数
int quad_capacity = 0;          // 初始四元式容量

// 获取四元式数组
Quadruple* get_quadruples() {
    return quadruples;
}

// 获取四元式数量
int get_quadruple_count() {
    return quad_count;
}

// 初始化四元式数组
void init_quadruples() {
    // 释放之前的内存（如果存在）
    if (quadruples != NULL) {
        free(quadruples);
    }
    
    // 初始化变量
    quad_capacity = 512;
    quad_count = 0;
    temp_var_count = 0;
    label_count = 0;
    
    // 分配内存
    quadruples = (Quadruple*)malloc(quad_capacity * sizeof(Quadruple));
    if (!quadruples) {
        printf("内存分配失败\n");
        exit(-1);
    }
}

// 释放四元式数组内存
void free_quadruples() {
    if (quadruples) {
        free(quadruples);
        quadruples = NULL;
    }
    quad_count = 0;
    temp_var_count = 0;
    label_count = 0;
    quad_capacity = 0;
}

// 生成新的临时变量名
char* q_new_temp() {
    static char temp_name[32];
    sprintf(temp_name, "T%d", temp_var_count++);
    return strdup(temp_name);
}

// 生成新的标签名
char* q_new_label() {
    static char label_name[32];
    sprintf(label_name, "L%d", label_count++);
    return strdup(label_name);
}

// 获取变量名
char* q_get_var_name(intptr_t *id) {
    if (!id) return "_";
    
    return (char*)*(id + Name);
}

// 生成四元式
void q_emit(const char* op, const char* arg1, const char* arg2, const char* result) {
    if (quad_count >= quad_capacity) {
        quad_capacity *= 2;
        quadruples = (Quadruple*)realloc(quadruples, quad_capacity * sizeof(Quadruple));
        if (!quadruples) {
            printf("内存分配失败\n");
            exit(-1);
        }
    }
    
    strncpy(quadruples[quad_count].op, op, sizeof(quadruples[quad_count].op) - 1);
    strncpy(quadruples[quad_count].arg1, arg1 ? arg1 : "_", sizeof(quadruples[quad_count].arg1) - 1);
    strncpy(quadruples[quad_count].arg2, arg2 ? arg2 : "_", sizeof(quadruples[quad_count].arg2) - 1);
    strncpy(quadruples[quad_count].result, result ? result : "_", sizeof(quadruples[quad_count].result) - 1);
    
    quadruples[quad_count].op[sizeof(quadruples[quad_count].op) - 1] = '\0';
    quadruples[quad_count].arg1[sizeof(quadruples[quad_count].arg1) - 1] = '\0';
    quadruples[quad_count].arg2[sizeof(quadruples[quad_count].arg2) - 1] = '\0';
    quadruples[quad_count].result[sizeof(quadruples[quad_count].result) - 1] = '\0';
    
    quad_count++;
}

// 打印四元式
void print_quadruples() {
    for (int i = 0; i < quad_count; i++) {
        printf("%d:['%s', '%s', '%s', '%s']\n", i, 
               quadruples[i].op, 
               quadruples[i].arg1, 
               quadruples[i].arg2, 
               quadruples[i].result);
    }
}

// 表达式解析，返回表达式结果的变量名
char* q_expression(int level) {
    // 单元表达式处理
    intptr_t *id;
    int tmp;
    char *result = NULL;
    char *left = NULL;
    char *right = NULL;
    char str_val[32];

    if (!token) {
        printf("%d: unexpected token EOF of expression\n", line);
        exit(-1);
    }
    
    // 处理基本单元和一元运算符
    if (token == Num) {
        sprintf(str_val, "%d", token_val);
        result = strdup(str_val);
        match(Num);
        expr_type = INT;
    }
    else if (token == Str) {
        // 字符串常量
        sprintf(str_val, "\"%s\"", (char *)token_val);
        result = strdup(str_val);
        match(Str);
        while (token == Str) {
            match(Str);
        }
        expr_type = PTR;
    }
    else if (token == Sizeof) {
        match(Sizeof);
        match('(');
        expr_type = INT;

        if (token == Int) {
            match(Int);
            sprintf(str_val, "%ld", sizeof(intptr_t));
        } else if (token == Char) {
            match(Char);
            expr_type = CHAR;
            sprintf(str_val, "%ld", sizeof(char));
        }

        while (token == Mul) {
            match(Mul);
            expr_type = expr_type + PTR;
        }

        match(')');
        result = strdup(str_val);
        expr_type = INT;
    }
    else if (token == Id) {
        match(Id);
        id = current_id;

        if (token == '(') {
            // 函数调用
            match('(');
            int arg_count = 0;

            // 处理参数
            while (token != ')') {
                char* arg = q_expression(Assign);
                q_emit("para", arg, "_", "_");
                arg_count++;
                
                if (token == ',') {
                    match(',');
                }
            }
            match(')');

            // 生成函数调用四元式
            result = q_new_temp();
            if (id[Class] == Sys) {
                q_emit("call", q_get_var_name(id), "_", result);
            } else if (id[Class] == Fun) {
                q_emit("call", q_get_var_name(id), "_", result);
            } else {
                printf("%d: bad function call\n", line);
                exit(-1);
            }
            
            expr_type = id[Type];
        }
        else if (id[Class] == Num) {
            // 枚举常量
            sprintf(str_val, "%ld", id[Value]);
            result = strdup(str_val);
            expr_type = INT;
        }
        else {
            // 变量
            result = q_get_var_name(id);
            expr_type = id[Type];
        }
    }
    else if (token == '(') {
        match('(');
        if (token == Int || token == Char) {
            tmp = (token == Char) ? CHAR : INT;
            match(token);
            while (token == Mul) {
                match(Mul);
                tmp = tmp + PTR;
            }
            
            match(')');
            result = q_expression(Inc);
            expr_type = tmp;
        } else {
            result = q_expression(Assign);
            match(')');
        }
    }
    else if (token == Mul) {
        // 取值操作符 *a
        match(Mul);
        result = q_expression(Inc);
        
        if (expr_type >= PTR) {
            expr_type = expr_type - PTR;
        } else {
            printf("%d: bad dereference\n", line);
            exit(-1);
        }
    }
    else if (token == And) {
        // 取地址操作符 &a
        match(And);
        result = q_expression(Inc);
        expr_type = expr_type + PTR;
    }
    else if (token == '!') {
        // 逻辑非
        match('!');
        result = q_expression(Inc);
        char* temp = q_new_temp();
        q_emit("==", result, "0", temp);
        result = temp;
        expr_type = INT;
    }
    else if (token == '~') {
        // 按位取反
        match('~');
        result = q_expression(Inc);
        char* temp = q_new_temp();
        q_emit("~", result, "_", temp);
        result = temp;
        expr_type = INT;
    }
    else if (token == Add) {
        // 一元加法
        match(Add);
        result = q_expression(Inc);
        expr_type = INT;
    }
    else if (token == Sub) {
        // 一元减法
        match(Sub);
        if (token == Num) {
            sprintf(str_val, "-%d", token_val);
            result = strdup(str_val);
            match(Num);
        } else {
            result = q_expression(Inc);
            char* temp = q_new_temp();
            q_emit("*", result, "-1", temp);
            result = temp;
        }
        expr_type = INT;
    }
    else if (token == Inc || token == Dec) {
        // 前缀自增/自减
        char op = (token == Inc) ? '+' : '-';
        char op_str[2] = {op, '\0'};
        match(token);
        result = q_expression(Inc);
        
        char* temp = q_new_temp();
        q_emit(op_str, result, "1", temp);
        q_emit("=", temp, "_", result);
        expr_type = INT;
    }
    else {
        printf("%d: bad expression\n", line);
        exit(-1);
    }

    // 处理二元运算符和后缀操作符
    while (token >= level) {
        // 保存左操作数和类型
        left = result;
        tmp = expr_type;
        
        if (token == Assign) {
            // 赋值操作 a = b
            match(Assign);
            right = q_expression(Assign);
            q_emit("=", right, "_", left);
            result = left;
            expr_type = tmp;
        }
        else if (token == Cond) {
            // 条件表达式 a ? b : c
            match(Cond);
            char* label1 = q_new_label();
            char* label2 = q_new_label();
            
            q_emit("jz", left, "_", label1);
            right = q_expression(Assign);
            
            if (token == ':') {
                match(':');
            } else {
                printf("%d: missing colon in conditional\n", line);
                exit(-1);
            }
            
            q_emit("jump", "_", "_", label2);
            q_emit("label", "_", "_", label1);
            
            char* else_expr = q_expression(Cond);
            result = q_new_temp();
            q_emit("=", right, "_", result);
            q_emit("=", else_expr, "_", result);
            
            q_emit("label", "_", "_", label2);
        }
        else if (token == Lor) {
            // 逻辑或
            match(Lor);
            char* label = q_new_label();
            
            q_emit("jnz", left, "_", label);
            right = q_expression(Lan);
            
            result = q_new_temp();
            q_emit("||", left, right, result);
            q_emit("label", "_", "_", label);
            expr_type = INT;
        }
        else if (token == Lan) {
            // 逻辑与
            match(Lan);
            char* label = q_new_label();
            
            q_emit("jz", left, "_", label);
            right = q_expression(Or);
            
            result = q_new_temp();
            q_emit("&&", left, right, result);
            q_emit("label", "_", "_", label);
            expr_type = INT;
        }
        else if (token == Or) {
            // 按位或
            match(Or);
            right = q_expression(Xor);
            result = q_new_temp();
            q_emit("|", left, right, result);
            expr_type = INT;
        }
        else if (token == Xor) {
            // 按位异或
            match(Xor);
            right = q_expression(And);
            result = q_new_temp();
            q_emit("^", left, right, result);
            expr_type = INT;
        }
        else if (token == And) {
            // 按位与
            match(And);
            right = q_expression(Eq);
            result = q_new_temp();
            q_emit("&", left, right, result);
            expr_type = INT;
        }
        else if (token == Eq) {
            // 等于
            match(Eq);
            right = q_expression(Ne);
            result = q_new_temp();
            q_emit("==", left, right, result);
            expr_type = INT;
        }
        else if (token == Ne) {
            // 不等于
            match(Ne);
            right = q_expression(Lt);
            result = q_new_temp();
            q_emit("!=", left, right, result);
            expr_type = INT;
        }
        else if (token == Lt) {
            // 小于
            match(Lt);
            right = q_expression(Shl);
            result = q_new_temp();
            q_emit("<", left, right, result);
            expr_type = INT;
        }
        else if (token == Gt) {
            // 大于
            match(Gt);
            right = q_expression(Shl);
            result = q_new_temp();
            q_emit(">", left, right, result);
            expr_type = INT;
        }
        else if (token == Le) {
            // 小于等于
            match(Le);
            right = q_expression(Shl);
            result = q_new_temp();
            q_emit("<=", left, right, result);
            expr_type = INT;
        }
        else if (token == Ge) {
            // 大于等于
            match(Ge);
            right = q_expression(Shl);
            result = q_new_temp();
            q_emit(">=", left, right, result);
            expr_type = INT;
        }
        else if (token == Shl) {
            // 左移
            match(Shl);
            right = q_expression(Add);
            result = q_new_temp();
            q_emit("<<", left, right, result);
            expr_type = INT;
        }
        else if (token == Shr) {
            // 右移
            match(Shr);
            right = q_expression(Add);
            result = q_new_temp();
            q_emit(">>", left, right, result);
            expr_type = INT;
        }
        else if (token == Add) {
            // 加法
            match(Add);
            right = q_expression(Mul);
            result = q_new_temp();
            q_emit("+", left, right, result);
            expr_type = tmp;
        }
        else if (token == Sub) {
            // 减法
            match(Sub);
            right = q_expression(Mul);
            result = q_new_temp();
            q_emit("-", left, right, result);
            expr_type = tmp;
        }
        else if (token == Mul) {
            // 乘法
            match(Mul);
            right = q_expression(Inc);
            result = q_new_temp();
            q_emit("*", left, right, result);
            expr_type = tmp;
        }
        else if (token == Div) {
            // 除法
            match(Div);
            right = q_expression(Inc);
            result = q_new_temp();
            q_emit("/", left, right, result);
            expr_type = tmp;
        }
        else if (token == Mod) {
            // 取模
            match(Mod);
            right = q_expression(Inc);
            result = q_new_temp();
            q_emit("%", left, right, result);
            expr_type = tmp;
        }
        else if (token == Inc || token == Dec) {
            // 后缀自增/自减
            char op = (token == Inc) ? '+' : '-';
            char op_str[2] = {op, '\0'};
            
            result = q_new_temp();
            q_emit("=", left, "_", result);
            
            char* temp = q_new_temp();
            q_emit(op_str, left, "1", temp);
            q_emit("=", temp, "_", left);
            
            match(token);
        }
        else if (token == Brak) {
            // 数组访问 a[b]
            match(Brak);
            right = q_expression(Assign);
            match(']');
            
            result = q_new_temp();
            if (tmp > PTR) {
                char* index_temp = q_new_temp();
                q_emit("*", right, "4", index_temp);  // 假设 intptr_t 大小为4字节
                q_emit("+", left, index_temp, result);
            } else if (tmp < PTR) {
                printf("%d: pointer type expected\n", line);
                exit(-1);
            } else {
                q_emit("+", left, right, result);
            }
            
            expr_type = tmp - PTR;
        }
        else {
            printf("%d: compiler error, token = %d\n", line, token);
            exit(-1);
        }
    }
    
    return result;
}

void q_statement() {
    // 处理各种语句
    char *expr_result;
    char *cond_result;
    char *loop_start;
    char *loop_end;
    char *else_label;
    char label_buf[32];
    int loop_label_idx;
    
    if (token == If) {
        // if语句
        match(If);
        match('(');
        cond_result = q_expression(Assign);
        match(')');
        
        // 生成条件跳转
        else_label = q_new_label();
        q_emit("jz", cond_result, "_", else_label);
        
        // 处理if主体
        q_statement();
        
        if (token == Else) {
            // 如果有else部分
            match(Else);
            char* end_label = q_new_label();
            q_emit("jump", "_", "_", end_label);
            q_emit("label", "_", "_", else_label);
            q_statement();
            q_emit("label", "_", "_", end_label);
        } else {
            // 没有else，直接标记else位置
            q_emit("label", "_", "_", else_label);
        }
    }
    else if (token == While) {
        // while循环
        match(While);
        
        // 记录循环开始位置
        loop_start = q_new_label();
        loop_end = q_new_label();
        q_emit("label", "_", "_", loop_start);
        
        match('(');
        cond_result = q_expression(Assign);
        match(')');
        
        // 条件判断
        q_emit("jz", cond_result, "_", loop_end);
        
        // 循环体
        q_statement();
        
        // 跳回循环开始
        q_emit("jump", "_", "_", loop_start);
        q_emit("label", "_", "_", loop_end);
    }
    else if (token == For) {
        /*
            标准for循环优化结构:
            for(<init>; <cond>; <iter>) {    <init>
                <statement>                  a: <cond>
            }                                   JZ b
                                                <statement>
                                                <iter>
                                                JMP a
                                             b:
        */
        match(For);
        match('(');
        
        // 初始化表达式
        if (token != ';') {
            q_expression(Assign);
        }
        match(';');
        
        // 创建所需标签
        char* condition_label = q_new_label();    // 条件判断标签
        char* end_label = q_new_label();          // 循环结束标签
        
        // 条件判断标签
        q_emit("label", "_", "_", condition_label);
        
        // 条件表达式
        if (token != ';') {
            cond_result = q_expression(Assign);
            q_emit("jz", cond_result, "_", end_label); // 条件为假跳转到循环结束
        }
        match(';');
        
        // 保存迭代表达式，但不立即生成代码
        int iter_pos = quad_count; // 记录当前四元式数量
        if (token != ')') {
            q_expression(Assign); // 生成迭代表达式的四元式
        }
        int iter_end = quad_count; // 记录迭代表达式结束位置
        
        // 保存迭代表达式的四元式
        Quadruple* iter_code = NULL;
        int iter_count = iter_end - iter_pos;
        
        if (iter_count > 0) {
            iter_code = (Quadruple*)malloc(sizeof(Quadruple) * iter_count);
            if (!iter_code) {
                printf("内存分配失败\n");
                exit(-1);
            }
            
            // 复制迭代表达式的四元式
            memcpy(iter_code, &quadruples[iter_pos], sizeof(Quadruple) * iter_count);
            
            // 回退四元式计数，等于删除了已生成的迭代表达式
            quad_count = iter_pos;
        }
        
        match(')');
        
        // 执行循环体
        q_statement();
        
        // 在循环体后添加迭代表达式
        if (iter_count > 0) {
            // 复制之前保存的迭代表达式四元式
            for (int i = 0; i < iter_count; i++) {
                quadruples[quad_count++] = iter_code[i];
            }
            free(iter_code);
        }
        
        // 迭代表达式执行完后跳回条件判断
        q_emit("jump", "_", "_", condition_label);
        
        // 循环结束的标签
        q_emit("label", "_", "_", end_label);
    }
    else if (token == '{') {
        // 代码块
        match('{');
        while (token != '}') {
            q_statement();
        }
        match('}');
    }
    else if (token == Return) {
        // return语句
        match(Return);
        
        if (token != ';') {
            expr_result = q_expression(Assign);
            q_emit("return", expr_result, "_", "_");
        } else {
            q_emit("return", "_", "_", "_");
        }
        
        match(';');
    }
    else if (token == ';') {
        // 空语句
        match(';');
    }
    else {
        // 表达式语句
        expr_result = q_expression(Assign);
        match(';');
    }
}

void q_function_parameter() {
    int type;
    int params = 0;
    
    while (token != ')') {
        type = INT;
        if (token == Int) {
            match(Int);
        } else if (token == Char) {
            type = CHAR;
            match(Char);
        }
        
        // 指针类型
        while (token == Mul) {
            match(Mul);
            type = type + PTR;
        }
        
        // 参数名
        if (token != Id) {
            printf("%d: bad parameter declaration\n", line);
            exit(-1);
        }
        if (current_id[Class] == Loc) {
            printf("%d: duplicate parameter declaration\n", line);
            exit(-1);
        }
        
        match(Id);
        
        // 存储局部变量
        current_id[BClass] = current_id[Class]; current_id[Class] = Loc;
        current_id[BType] = current_id[Type]; current_id[Type] = type;
        current_id[BValue] = current_id[Value]; current_id[Value] = params++;
        
        if (token == ',') {
            match(',');
        }
    }
    
    index_of_bp = params + 1;
}

void q_function_body() {
    int pos_local;
    int type;
    pos_local = index_of_bp;
    
    // 处理局部变量声明
    while (token == Int || token == Char) {
        basetype = (token == Int) ? INT : CHAR;
        match(token);
        
        while (token != ';') {
            type = basetype;
            while (token == Mul) {
                match(Mul);
                type = type + PTR;
            }
            
            if (token != Id) {
                printf("%d: bad local declaration\n", line);
                exit(-1);
            }
            if (current_id[Class] == Loc) {
                printf("%d: duplicate local declaration\n", line);
                exit(-1);
            }
            
            match(Id);
            
            // 存储局部变量
            current_id[BClass] = current_id[Class]; current_id[Class] = Loc;
            current_id[BType] = current_id[Type]; current_id[Type] = type;
            current_id[BValue] = current_id[Value]; current_id[Value] = ++pos_local;
            
            // 添加初始化处理
            if (token == Assign) {
                char* var_name = q_get_var_name(current_id);
                match(Assign);
                
                if (token == Str) {
                    char str_val[32];
                    sprintf(str_val, "\"%s\"", (char *)token_val);
                    q_emit("=", str_val, "_", var_name);
                    current_id[Dvalue] = token_val;
                    match(Str);
                } else if (token == Num) {
                    char num_val[32];
                    sprintf(num_val, "%d", token_val);
                    q_emit("=", num_val, "_", var_name);
                    current_id[Dvalue] = token_val;
                    match(Num);
                }
            }
            
            if (token == ',') {
                match(',');
            }
        }
        match(';');
    }
    
    // 处理语句
    while (token != '}') {
        q_statement();
    }
    
    // 函数返回(无返回值)
    q_emit("return", "_", "_", "_");
}

void q_function_declaration() {
    match('(');
    q_function_parameter();
    match(')');
    match('{');
    q_function_body();
    
    // 恢复局部变量声明
    current_id = symbols;
    while (current_id[Token]) {
        if (current_id[Class] == Loc) {
            current_id[Class] = current_id[BClass];
            current_id[Type] = current_id[BType];
            current_id[Value] = current_id[BValue];
        }
        current_id = current_id + IdSize;
    }
}

void q_enum_declaration() {
    int i = 0;
    while (token != '}') {
        if (token != Id) {
            printf("%d: bad enum identifier %d\n", line, token);
            exit(-1);
        }
        next();
        if (token == Assign) {
            next();
            if (token != Num) {
                printf("%d: bad enum initializer\n", line);
                exit(-1);
            }
            i = token_val;
            next();
        }
        
        current_id[Class] = Num;
        current_id[Type] = INT;
        current_id[Value] = i++;
        
        if (token == ',') {
            next();
        }
    }
}

void q_global_declaration() {
    int type;
    basetype = INT;
    
    // 处理枚举
    if (token == Enum) {
        match(Enum);
        if (token != '{') {
            match(Id);
        }
        if (token == '{') {
            match('{');
            q_enum_declaration();
            match('}');
        }
        match(';');
        return;
    }
    
    // 处理类型
    if (token == Int) {
        match(Int);
    } else if (token == Char) {
        match(Char);
        basetype = CHAR;
    }
    
    // 处理变量声明和函数声明
    while (token != ';' && token != '}') {
        type = basetype;
        while (token == Mul) {
            match(Mul);
            type = type + PTR;
        }
        
        if (token != Id) {
            printf("%d: bad global declaration\n", line);
            exit(-1);
        }
        if (current_id[Class]) {
            printf("%d: duplicate global declaration\n", line);
            exit(-1);
        }
        
        match(Id);
        current_id[Type] = type;
        
        if (token == '(') {
            current_id[Class] = Fun;
            // 生成函数声明四元式
            q_emit("func", q_get_var_name(current_id), "_", "_");
            q_function_declaration();
        } else {
            current_id[Class] = Glo;
            // 全局变量初始化处理
            char* var_name = q_get_var_name(current_id);
            
            if (token == Assign) {
                match(Assign);
                
                if (token == Str) {
                    char str_val[32];
                    sprintf(str_val, "\"%s\"", (char *)token_val);
                    q_emit("=", str_val, "_", var_name);
                    current_id[Dvalue] = token_val;
                    match(Str);
                } else if (token == Num) {
                    char num_val[32];
                    sprintf(num_val, "%d", token_val);
                    q_emit("=", num_val, "_", var_name);
                    current_id[Dvalue] = token_val;
                    match(Num);
                }
            }
        }
        
        if (token == ',') {
            match(',');
        }
    }
    
    next();
}

void q_parse_program() {
    // 初始化四元式
    init_quadruples();
    
    // 获取下一个token
    next();
    while (token > 0) {
        q_global_declaration();
    }
    
    // 添加系统结束四元式
    q_emit("sys", "_", "_", "_");
}

void q_program() {
    q_parse_program();
}

void q_init_parser() {
    basetype = INT;
    expr_type = INT;
}
